package com.yr.ryjk.doctor.service;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import com.alibaba.fastjson.JSONObject;
import com.yr.ryjk.common.Constant;
import com.yr.ryjk.common.ErrorType;
import com.yr.ryjk.common.Pagination;
import com.yr.ryjk.doctor.dao.DoctorMapper;
import com.yr.ryjk.doctor.dao.DoctorRegisterMapper;
import com.yr.ryjk.doctor.entity.Doctor;
import com.yr.ryjk.doctor.entity.DoctorRegister;
import com.yr.ryjk.doctor.entity.FilterParam;
import com.yr.ryjk.doctor.vo.CensusVO;
import com.yr.ryjk.doctor.vo.DoctorVO;
import com.yr.ryjk.doctor.vo.DoctorVOCensus;
import com.yr.ryjk.doctor.vo.TotalCensusVO;
import com.yr.ryjk.doctorduty.dao.DoctorDutyMapper;
import com.yr.ryjk.doctorduty.entity.DoctorDuty;
import com.yr.ryjk.expert.dao.DoctorExpertMapper;
import com.yr.ryjk.expert.entity.DoctorExpert;
import com.yr.ryjk.hospital.service.IHospitalService;
import com.yr.ryjk.jpush.JPushType;
import com.yr.ryjk.jpush.JpushMessage;
import com.yr.ryjk.jpush.JpushSendService;
import com.yr.ryjk.param.dao.ParamMapper;
import com.yr.ryjk.param.entity.Key;
import com.yr.ryjk.param.entity.Param;
import com.yr.ryjk.redis.JedisUtil;
import com.yr.ryjk.sms.SendSmsUtil;
import com.yr.ryjk.user.dao.UserMapper;
import com.yr.ryjk.user.entity.User;
import com.yr.ryjk.util.IDGenerator;
import com.yr.ryjk.util.JSONUtil;

@Service
public class DoctorService implements IDoctorService{
	@Autowired
	private DoctorMapper doctorMapper;
	@Autowired
	private DoctorDutyMapper doctorDutyMapper;
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private DoctorRegisterMapper doctorRegisterMapper;
	@Autowired
	private IHospitalService hospitalService;
	@Autowired
	private DoctorExpertMapper doctorExpertMapper;
	@Autowired
	private ParamMapper paramMapper;
	
	@Override
	public Map<String, Object> addRegister(String phone, String password,String checkcode) {
		//1.判断手机验证码
		String checkcodeInRedis=JedisUtil.getCheckcodeByPhone(phone);
		if(checkcodeInRedis==null){
			return JSONUtil.getJSON(ErrorType.CHECKCODE_NOT_EXSIT_ERROR);
		}else if(!checkcodeInRedis.equals(checkcode)){
			return JSONUtil.getJSON(ErrorType.CHECKCODE_ERROR);
		}else {
			//2.判断手机号是否已注册
			Doctor doctor=doctorMapper.selectByPhone(phone);
			if(doctor!=null){
				return JSONUtil.getJSON(ErrorType.PHONE_HAS_REGISTERED_ERROR);
			}
			User user=userMapper.selectUserByPhone(phone);
			if(user!=null){
				return JSONUtil.getJSON(ErrorType.PHONE_HAS_REGISTERED_ERROR);
			}
			//3.插入医生注册表
			DoctorRegister dg=doctorRegisterMapper.selectByPhone(phone);
			if(dg==null){
				dg=new DoctorRegister();
				dg.setId(IDGenerator.gen32UUID());
				dg.setPhone(phone);
				dg.setPassword(DigestUtils.md5DigestAsHex(password.getBytes()));
				dg.setRegisterProgress(1);      //注册进度
				dg.setRegisterTime(new Date()); //注册时间
				doctorRegisterMapper.insert(dg);
			}else {
				return JSONUtil.getJSON(ErrorType.PHONE_HAS_REGISTERED_ERROR,dg);
			}
		}
		return JSONUtil.getJSON(ErrorType.SUCCESS);
	}

	@Override
	public void addRegister2(DoctorRegister dg) {
		DoctorRegister dgInDB=doctorRegisterMapper.selectByPhone(dg.getPhone());
		if(dgInDB!=null){
			dg.setId(dgInDB.getId());
			dg.setRegisterProgress(2);  //注册进度
			doctorRegisterMapper.updateByPrimaryKeySelective(dg);
		}
	}

	@Override
	public void addRegister3(String phone, String halfPicUrl, String cardUrl,
			String workProofPicUrl) {
		DoctorRegister dg=doctorRegisterMapper.selectByPhone(phone);
		if(dg!=null){
			dg.setRegisterProgress(3);       //注册进度
			dg.setHalfPicUrl(halfPicUrl);
			dg.setCardUrl(cardUrl);
			dg.setWorkProofPicUrl(workProofPicUrl);
			doctorRegisterMapper.updateByPrimaryKeySelective(dg);
		}
	}
	@Override
	public Map<String, Object> updatelogin(String phone, String password,String jpushKey) throws IllegalAccessException, InvocationTargetException {
		//1.验证信息
		Doctor doctor=doctorMapper.selectByPhone(phone);
		if(doctor!=null){         //用户存在于doctor表中
			if(DigestUtils.md5DigestAsHex(password.getBytes()).equals(doctor.getPassword())){
				String token=IDGenerator.gen32UUID();  //令牌
				doctorMapper.updateLoginTime(new Date(),phone); //更新登陆时间
				
				//2.登录互斥，不允许多部设备同时登录一个帐号
				final String jpushKeyInRedis=JedisUtil.getJPushKeyByPhone(phone);
				if(jpushKeyInRedis!=null&&!jpushKeyInRedis.equals(jpushKey)){        //使其他设备下线
					new Thread(new Runnable() {              //新开线程，避免阻塞
						@Override
						public void run() {
							try {
								final JpushMessage msg = new JpushMessage();
								msg.setName("doctor");             //特殊用途，用于告诉app登录用户的身份
								msg.setType(JPushType.need_login);
								
								String jpushMap =  JSONObject.toJSON(msg).toString();
								JpushSendService.sendAndroidMessage(jpushMap, new String[]{jpushKeyInRedis});
							} catch (Exception e) {
								e.printStackTrace();
								//消息推送异常,是可以允许的异常
							}
						}
					}).start();
				}
				
				//3.覆盖登录信息
				JedisUtil.putPhoneTokenMap(phone, token);
				JedisUtil.putTokenPhoneMap(token, phone);
				JedisUtil.putPhoneJPushMap(phone, jpushKey);
				JedisUtil.putJPushPhoneMap(jpushKey, phone);
				
				//4.将医生信息返回给app
				DoctorVO dvo=doctorMapper.selectVoById(doctor.getId());
				dvo.setCheckStatus(1);            //为解决蔡阳春的checkStatus被赋值为默认值0的问题
				dvo.setToken(token);
				return JSONUtil.getJSON(ErrorType.SUCCESS,dvo);
			}else {
				return JSONUtil.getJSON(ErrorType.PASSWORD_ERROR);
			}
		}else {                  //doctor表中无该帐号,从doctor_register表中查询
			DoctorRegister dg=doctorRegisterMapper.selectByPhone(phone);
			if(dg==null){
				return JSONUtil.getJSON(ErrorType.LOGIN_ERROR);
			}
			return JSONUtil.getJSON(ErrorType.SUCCESS,dg);
		}
	}
	
	@Override
	public Map<String, Object> updateResetPassword(String phone,
			String newPassword, String checkcode) {
		String checkcodeInRedis=JedisUtil.getCheckcodeByPhone(phone);
		if(checkcodeInRedis==null){
			return JSONUtil.getJSON(ErrorType.CHECKCODE_NOT_EXSIT_ERROR);
		}else if(!checkcodeInRedis.equals(checkcode)){
			return JSONUtil.getJSON(ErrorType.CHECKCODE_ERROR);
		}else {
			doctorMapper.updatePasswordByPhone(phone,DigestUtils.md5DigestAsHex(newPassword.getBytes()));
			return JSONUtil.getJSON(ErrorType.SUCCESS);
		}
	}
	@Override
	public Map<String, Object> updatePassword(String oldPassword,
			String newPassword, String token) {
		String phone=JedisUtil.getPhoneByToken(token);
		if(phone!=null){
			Doctor doctor=doctorMapper.selectByPhone(phone);
			if(doctor!=null&&doctor.getPassword().equals(DigestUtils.md5DigestAsHex(oldPassword.getBytes()))){
				doctorMapper.updatePasswordByPhone(phone, DigestUtils.md5DigestAsHex(newPassword.getBytes()));
				return JSONUtil.getJSON(ErrorType.SUCCESS);
			}else {
				return JSONUtil.getJSON(ErrorType.PASSWORD_ERROR);
			}
		}else {
			return JSONUtil.getJSON(ErrorType.TOKEN_ERROR);
		}
	}

	@Override
	public DoctorVO getDoctorById(String id) {
		DoctorVO doctor=doctorMapper.selectVoById(id);
		if(doctor==null){
			doctor=doctorRegisterMapper.selectVoById(id);
		}
		return doctor;
	}
	
	@Override
	public Map<String, Object> getListOfPage(int pageNo, int pageSize,int status,
			String name, String phone,String isDown) {
		Map<String, Object> map=new HashMap<String, Object>();
		Pagination page=new Pagination();
		int count;
		switch (status) {
		case 0:                  //待审核
		case 2:                  //已审核驳回
			List<DoctorRegister> list=doctorRegisterMapper.selectOfPage((pageNo-1)*pageSize,pageSize,status);
			count=doctorRegisterMapper.selectCount(status);
			
			page.setPageNo(pageNo);
			page.setPageSize(pageSize);
			page.setTotalCount(count);
			
			map.put("list", list);
			map.put("pagination", page);
			
			break;
		case 1:                  //已审核通过
			List<Doctor> list2=doctorMapper.selectOfPage((pageNo-1)*pageSize,pageSize,name,phone,isDown);
			count=doctorMapper.selectCount(name,phone,isDown);
			
			page.setPageNo(pageNo);
			page.setPageSize(pageSize);
			page.setTotalCount(count);
			
			map.put("list", list2);
			map.put("pagination", page);
			break;
		default:
			break;
		}
		return map;
	}
	
	@Override
	public void updateCheck(String ids, Integer action,String reason) throws IllegalAccessException, InvocationTargetException {
		if(action==0){                     //审核通过
			List<DoctorRegister> list=doctorRegisterMapper.selectByIds(ids);
			for(DoctorRegister dg:list){
				//1.处理医院信息
				String hid=hospitalService.addHandleRegisterHospital(dg.getHospital());
				//2.将信息插入到doctor表
				Doctor doctor=new Doctor();
				BeanUtils.copyProperties(doctor, dg);//复制属性
				doctor.setDepId(dg.getDepartment());
				doctor.setDutyId(dg.getDuty());
				doctor.setHospitalId(hid);
				doctor.setCoin(0);
				doctor.setCoinMd5(DigestUtils.md5DigestAsHex((0+Constant.COIN_MD5_SECRET_KEY).getBytes()));
				doctor.setTotalGainCoin(0);
				doctor.setScanTimes(0);
				//如果已存在该信息,则只需要更新信息
				if(doctorMapper.selectByPrimaryKey(doctor.getId())==null){
					doctorMapper.insert(doctor);
				}else{
					doctorMapper.updateByPrimaryKeySelective(doctor);
				}
			}
			//3.更新doctor_register状态
			doctorRegisterMapper.updateStatusAndReasonByIds(action+1,null,ids);
		}else if(action==1){               //审核驳回
			doctorRegisterMapper.updateStatusAndReasonByIds(action+1,reason,ids);
		}
	}

	@Override
	public Map<String, Object> getListOfDepartment(int pageNo, int pageSize,String token,FilterParam filterParam) {
		String phone=JedisUtil.getPhoneByToken(token);
		if(phone!=null){
			Map<String,Object> params=new HashMap<String,Object>();
			params.put("start", (pageNo-1)*pageSize);
			params.put("limit", pageSize);
			params.put("phone", phone);
			params.put("hospitalLevel", filterParam.getHospitalLevel());
			params.put("departmentId", filterParam.getDepartmentId());
			params.put("dutyId", filterParam.getDutyId());
			
			List<DoctorVOCensus> list=doctorMapper.selectByDepartment(params);
			int count=doctorMapper.selectCountByDepartment(params);
			int coin=userMapper.selectCoinByPhone(phone);
			
			Map<String, Object> map=new HashMap<String,Object>();
			map.put("list", list);
			map.put("pagination", new Pagination(pageSize, pageNo, count));
			map.put("coin", coin);
			return JSONUtil.getJSON(ErrorType.SUCCESS,map);
		}else {
			return JSONUtil.getJSON(ErrorType.TOKEN_ERROR);
		}
	}
	@Override
	public void updateIncreaseScanTimes(String doctorId) {
		doctorMapper.updateIncreaseScanTimes(doctorId);
	}

	@Override
	public CensusVO getCensusData(String token) {
		String phone=JedisUtil.getPhoneByToken(token);
		return doctorMapper.selectCensus(phone);
	}

	@Override
	public Map<String, Object> selectSearch(int pageNo, int pageSize,
			String keyword, String token,FilterParam filterParam) {
		String phone=JedisUtil.getPhoneByToken(token);
		if(phone!=null){
			Map<String,Object> params=new HashMap<String,Object>();
			params.put("start", (pageNo-1)*pageSize);
			params.put("limit", pageSize);
			params.put("keyword", keyword);
			params.put("phone", phone);
			params.put("hospitalLevel", filterParam.getHospitalLevel());
			params.put("departmentId", filterParam.getDepartmentId());
			params.put("dutyId", filterParam.getDutyId());
			
			List<DoctorVO> list=doctorMapper.selectSearch(params);
			int count=doctorMapper.selectCountSearch(params);
			int coin=userMapper.selectCoinByPhone(phone);
			
			Map<String, Object> map=new HashMap<String,Object>();
			map.put("list", list);
			map.put("pagination", new Pagination(pageSize, pageNo, count));
			map.put("coin", coin);
			return JSONUtil.getJSON(ErrorType.SUCCESS,map);
		}else {
			return JSONUtil.getJSON(ErrorType.TOKEN_ERROR);
		}
	}

	@Override
	public Map<String, Object> selectByType(int pageNo, int pageSize,
			String typeId, String name, String phone) {
		Map<String, Object> map=new HashMap<String,Object>();
		int page=(pageNo-1)*pageSize;
		map.put("list", doctorMapper.selectByType(page,pageSize,typeId,name,phone));
		map.put("pagination", new Pagination(pageSize, pageNo, doctorMapper.selectByTypeCount(typeId, name, phone)));
		return map;
	}

	@Override
	public void modifyDocInGroup(String ids,String group) {
		String [] items=ids.split(",");
		for(String id:items){
			DoctorExpert dExpert=new DoctorExpert(IDGenerator.gen32UUID(),id,group);
			doctorExpertMapper.insertSelective(dExpert);
		}
	}

	@Override
	public Map<String, Object> updateAskPrice(int askPrice, String token) {
		String phone=JedisUtil.getPhoneByToken(token);
		Doctor doctor=doctorMapper.selectByPhone(phone);
		DoctorDuty doctorduty=doctorDutyMapper.selectByPrimaryKey(doctor.getDutyId());
		if(askPrice<doctorduty.getMinPrice()||askPrice>doctorduty.getMaxPrice()){
			return JSONUtil.getJSON(ErrorType.ASKPRICE_OUT_OF_RANGE);
		}else{
			doctorMapper.updateAskPriceByPhone(askPrice,phone);
			return JSONUtil.getJSON(ErrorType.SUCCESS); 
		}
	}

	@Override
	public Map<String, Object> addDoctor(Doctor doctor) {
		final String phone=doctor.getPhone(); 
		//1.判断手机号是否已注册
		Doctor doctorInDb=doctorMapper.selectByPhone(phone);
		if(doctorInDb!=null){
			return JSONUtil.getJSON(ErrorType.PHONE_HAS_REGISTERED_ERROR);
		}
		User user=userMapper.selectUserByPhone(phone);
		if(user!=null){
			return JSONUtil.getJSON(ErrorType.PHONE_HAS_REGISTERED_ERROR);
		}
				
		//2.添加到数据库
		final Param param=paramMapper.selectByPrimaryKey(Key.admin_default_password.getKey());
		
		doctor.setId(IDGenerator.gen32UUID());
		String pwd=DigestUtils.md5DigestAsHex(param.getValue().getBytes());
		doctor.setPassword(pwd);
	    doctor.setCoin(0);
	    doctor.setCoinMd5(DigestUtils.md5DigestAsHex((0+Constant.COIN_MD5_SECRET_KEY).getBytes()));
		doctor.setRegisterTime(new Date());
	    
		int count=doctorMapper.insert(doctor);
		if(count==1){
			new Thread(new Runnable() {
				@Override
				public void run() {
					SendSmsUtil.sendSms(phone, "您的账号已经添加成功，初始密码为"+param.getValue());
				}
			}).start();
			return JSONUtil.getJSON(ErrorType.SUCCESS);
		}
		return JSONUtil.getJSON(ErrorType.SERVER_ERROR);
	}

	@Override
	public Map<String, Object> modifyDoctorInfo(Doctor doctor) 
	{
		doctorMapper.updateByPrimaryKey(doctor);
		return JSONUtil.getJSON(ErrorType.SUCCESS);
	}

	@Override
	public TotalCensusVO getTotalCensus(String docId) {
		return doctorMapper.selectTotalVoById(docId);
	}

	@Override
	public void modifyDoctorDown(String docId,int isDown) {
		doctorMapper.updateDoctorById(docId,isDown);
	}
}